\section{创建数据库} % (fold)
\label{sec:创建数据库}
在开始处理数据库之前，必须确定需求。网站的需求规定了应该如何设计数据库。

\subsection{命名数据库的元素} % (fold)
\label{sub:命名数据库的元素}
精确来说，数据库、表和列名称的长度限制为64个字节。虽然在有的系统中，数据库和表的名称不区分大小写，但我们建议总是区分大小写，并将名称全部小写。\cite{Ullman-2014}
\begin{enumerate}
  \item 在使用数据库前，我们需要创建数据库，而创建数据库，首要的问题就是确定数据库的名称。主要确保数据库名称对于MySQL服务器是唯一的即可。
  \item 确定表名称。数据库中表的名称必须唯一。
  \item 确定表中列的名称。命名时尽可能避免与MySQL的关键字冲突。
\end{enumerate}

\subsection{确定列类型和大小} % (fold)
\label{sub:确定列类型和大小}
一旦确定了数据库所需的所有表和列，就应该确定每个列的数据类型。MySQL要求明确指定每个列的信息类型。
\begin{enumerate}
  \item 字符串
  \item 数字
  \item 日期和时间
\end{enumerate}

列数据类型的选择不仅仅指示数据库存储什么信息，还会影响到数据库的总体性能。开发人员应该根据网站实际需求，合理确定数据类型。MySQL常用数据类型见表\ref{tab:MySQL常用数据类型}。

\begin{table}[htbp]
  \caption{MySQL常用数据类型}
    \begin{tabularx}{\linewidth}{l|>{\hsize=.5\hsize}X|>{\hsize=1.5\hsize}X}
    \toprule
    {类型}    & {大小}    & {描述} \\
    \midrule
    char[length] & length字节 & 定长字段，长度为0-255个字符 \\
    varchar[length] & string长度+1字节或string长度+2字节 & 变长字段，长度为0-65535个字符 \\
    tinytext & string长度+1字节 & 字符串，最大长度为255个字符 \\
    mediumtext & string长度+2字节 & 字符串，最大长度为16777215个字符 \\
    longtext & string长度+4字节 & 字符串，最大长度为4294967295个字符 \\
    tinyint[length] & 1字节   & 范围：-128-127，或者0-255 \\
    smallint[length] & 2字节   & 范围：-32768-32767，或者0-65535 \\
    mediumint[length] & 3字节   & 范围：-8388608-8388607，或者0-16777215 \\
    int[length] & 4字节   & 范围：-2147483648-2147483647，或者0-4294967295 \\
    bigint[length] & 8字节   & 范围：-923372036854775808-923372036854775807，或者0-18446774073709551615 \\
    float[length,decimals] & 4字节   & 具有浮动小数点的较小的数 \\
    decimal[length,decimals] & 8字节   & 具有浮动小数点的较大的数 \\
    date  & 3字节   & 采用YYYY-MM-DD的格式 \\
    datetime & 8字节   & 采用YYYY-MM-DD HH:MM:SS格式 \\
    timestamp & 4字节   & 采用YYYYMMDDHHMMSS格式，从1970-2038年 \\
    time & 3字节 & 采用HH:MM:SS格式 \\
    enum & 1或者2字节 & enumeration（枚举）的简写，每一列都可以具有多个可能的值 \\
    set & 1、2、3、4或者8字节 & 与enum一样，只不过每一列都可以具有多个可能的值 \\
    \bottomrule
    \end{tabularx}
     \label{tab:MySQL常用数据类型}%
\end{table}

类型中可选的length属性，用来限制大小，这种对于列中存储数据量的限制，其目的在于保障性能。

与文本类型的长度属性不同，数字类型中的长度属性不会影响列中可以存储的值的范围。对于整数，长度为显示宽度；对于小数，长度为可以存储的总位数。

timestamp字段类型的值，会在发生insert或者update时，自动设置为当前日期和时间。

MySQL还具有文本类型的多种变体。这些类型是：binary、varbinary、tinyblob、mediumblob和longblob。这些类型用于存储文件或加密数据。
\begin{myremark}{char与varchar}
    char与varchar这两种类型都存储字符串，并且可以设置固定的最大长度。他们之间的区别是，存储为char的任何内容将存储为列长度的字符串，如果不够长度，将用空格填充够（从数据库取出时又将删除多余空格）。而varchar列中存储的字符串只需要与字符串本身一样长的空间。

    从性能角度讲，数据库处理定长的char类型时速度更快。
\end{myremark}
enum和set类型，允许为字段定义一系列可接受的值，enum可以从数千个可能的值中取一个值，而set允许从最多64个可能的值中取多个值。

在确定列应该为文本、数字，还是日期类型后，再为每一列选择最合适的子类型。

选择好数据子类型后，应该基于个能最大的输入，把字段的大小限制为尽可能小的值。

\subsection{选择其他的列属性} % (fold)
\label{sub:选择其他的列属性}
除了决定列的类型和大小外，还应该考虑列的一些其他属性，如是否为空、默认值、索引、键和自动增加等属性。

首先，不管什么类型，每一列都可以定义为NOT NULL。理想情况下，在正确设计的数据库中，每张表每一行的每一列都应该有一个值，NOT NULL将强制一个字段具有值。

在创建表时，还可以为列制定一个默认值。如：

\begin{lstlisting}
gender ENUM('M', 'F') default 'F'
\end{lstlisting}

gender列，在添加记录时，如果没有为其指定值，则会使用默认值'F'。

注意，text列不能设置默认值。

数据类型标记为unsigned时，数字限制为整数或0，还可以把数字类型标记为ZERO-FILL，这意味着将用0填充任何多余的空间。

数据库中的索引（index）是请求数据库留意特定列或者列组合的值得一种方式，通过索引，在检索记录时会提高性能，但是在数据变动后，需要重新建立索引。

数据库中的键（key）是用于设计数据库的规范化过程的组成部分，有两种类型的键：主键（primary key）和外键（foreign key）。每张表都应该有一个主键，一个表中的主键通常被链接为另一张表中的外键。

表中的主键应该遵守以下规则：
\begin{enumerate}
    \item 它必须总是具有一个值。
    \item 它的值确定后不再变化。
    \item 它的值不能重复。
\end{enumerate}

在MySQL中，可以通过设置AUTO\_INCREMENT描述为数字列自动增加数值。
